#ifndef PROCESSMANAGER_H
#define PROCESSMANAGER_H

#include <Globals.h>
#include <MemoryManagement.h>
#include <Process.h>
#include <Map.h>
#include <Resource.h>

#define KERNEL_STACK_SIZE  0x2000

/**
  Syscall interface.
**/
namespace ProcessManager_IF
{
  const int getProcess =0;
}

/**
	@author James Molloy <james@jamesmolloy.co.uk>
*/
class ProcessManager
{

// Process can access our "processes" member.
friend class Process;

public:
  ProcessManager();

  ~ProcessManager();
  
  /**
    Initialises the process manager. Must be called after the kernel heap
    has been initialised.
  **/
  void init();
  
  /**
    Switches the currently running process to user mode (ring 3). After this
    has been done, the process can no longer perform privileged instructions.
  **/
  void switchToUserMode();
  
  /**
    Gets the process corresponding to 'pid'. Defaults to the current
    process.
  **/
  Process *getProcess(int pid=-1)
  {
    if (pid == -1)
    {
      return currentProcess;
    }
    else
    {
      return processes.lookup(pid);
    }
  }
  u32int getProcessResource(int pid);
  
  /**
    Gets the current value of and increments the nextProcessId.
  **/
  u32int nextPid()
  {
    return nextProcessId++;
  }
  
  /**
    Switches process from currentProcess to p
  **/
  void switchTo(Process *p);
  
  /**
    Runs the short term scheduler
  **/
  void shortTermSchedule();
  
  /**
    Removes a process from all queues.
  **/
  void processDying(u32int pid);
  
  /**
    Causes the currently running process to be rescheduled in favour of
    another. The process that replaces it is specified by 'pid', if
    'pid' is non-zombie. Else, and if pid is -1, the next available
    process is scheduled.
  **/
  void yield(s32int pid);
  
  /**
    We are a system resource.
  **/
  Resource *resource;

private:
  /**
    Doctors the current process' return EIP to point to our global
    executeRpcRequests() function.
  **/
  void plantRpcCaller();

  /**
    The list of ready processes, ordered so that the first item is next to run.
    TODO: make this into a red-black tree.
  **/
  OrderedArray<Process *, 32> readyQueue;
  
  /**
    A map of processes to pids.
  **/
  Map<u32int, Process *, 32> processes;

  /**
    The process that is currently running.
  **/
  Process *currentProcess;

  /**
    The next process identifier that will be assigned.
  **/
  u32int nextProcessId;

};

#endif
